package org.homs.continuations.jdbc;

import org.homs.continuations.jdbc.session.SessionFactory;
import org.junit.After;
import org.junit.Before;

public abstract class AbstractDatabaseSetup {

	abstract protected String[] createStatements();

	abstract protected String[] insertStatements();

	abstract protected String[] dropStatements();

	@Before
	public void beforeTestMethod() {

		SessionFactory.getCurrentSession().beginTransaction();
		try {
			try {
				execute(createStatements());
			} catch (final Exception e) {
				try {
					execute(dropStatements());
					execute(createStatements());
				} catch (final Exception e2) {
					e.printStackTrace();
					throw new RuntimeException("error in " + this.getClass().getSimpleName(), e2);
				}
			}

			execute(insertStatements());

			SessionFactory.getCurrentSession().commit();
		} catch (final Exception e) {
			SessionFactory.getCurrentSession().rollback();
			throw new RuntimeException("error in " + this.getClass().getSimpleName(), e);
		}
	}

	@After
	public void afterTestMethod() {

		SessionFactory.getCurrentSession().beginTransaction();
		try {
			execute(dropStatements());

			SessionFactory.getCurrentSession().commit();
		} catch (final Exception e) {
			SessionFactory.getCurrentSession().rollback();
			throw new RuntimeException("error in " + this.getClass().getSimpleName(), e);
		}
	}

	protected void execute(final String... queries) {
		Throwable re = null;
		for (final String query : queries) {
			try {
				SessionFactory.getCurrentSession().getConnection().prepareStatement(query).execute();
			} catch (final Exception e) {
				if (re == null) {
					re = e;
				}
			}
		}
		if (re != null) {
			throw new RuntimeException(re);
		}
	}

}
